﻿using System.Linq;
using System.Windows.Navigation;
using System.Windows.Interactivity;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Controls;
using System.ServiceModel.DomainServices.Client.ApplicationServices;
using System;
using System.Collections.ObjectModel;

namespace OpenLightGroup.Common.Behaviors
{
    /// <summary>
    /// Action to redirect a users that is not in one of the allowed roles.
    /// </summary>
    [Description("Causes a redirect to occur if the current user is not in one of the allowed roles.")]
    public class RoleBasedRedirectAction
        : TriggerAction<Page>
    {
        /// <summary>
        /// Handles wiring up an event handler to the LoggedOut event if the InvokeOnLoggedOut property is set to true.
        /// </summary>
        public RoleBasedRedirectAction()
        {
            this.AllowedRoles = new Collection<string>();

            if (DesignTimeHelper.IsRuntime)
            {
                if (this.InvokeOnLoggedOut)
                {

                    WebContextBase.Current.Authentication.LoggedOut +=
                        new EventHandler<AuthenticationEventArgs>
                            ((sender, e) => this.Invoke(sender));

                }
            }
        }

        /// <summary>
        /// Url to redirect to if the user is not a member of a role in the AllowedRoles list.
        /// </summary>
        [Category("Redirect Settings")]
        [Obsolete("Use the new NavigationUri property instead. This will be removed in a future release.")]
        public string NavigationUrl { get; set; }

        /// <summary>
        /// Uri to redirect to if the user is not a member of a role in the AllowedRoles list.
        /// </summary>
        [Category("Redirect Settings")]
        public Uri NavigationUri { get; set; }

        /// <summary>
        /// List of allowed roles. Members of these roles will NOT be redirected.
        /// </summary>
        [Category("Redirect Settings")]
        [Description("A redirect will occur if the current user is NOT a member of one or more of these roles.")]
        public Collection<string> AllowedRoles { get; private set; }

        /// <summary>
        /// This option will override the AllowedRoles security check, and redirect regardless of the current users roles.
        /// </summary>
        [Category("Redirect Settings")]
        [Description("This option will override the AllowedRoles security check, and redirect regardless of the current users roles.")]
        public bool AlwaysRedirect { get; set; }

        /// <summary>
        /// If true this action will run when the current user logs out. Uses the WebContextBase.Current.Authentiction.LoggedOut event.
        /// </summary>
        [Category("Redirect Settings")]
        [Description("If true this action will run when the current user logs out. Uses the WebContextBase.Current.Authentiction.LoggedOut event.")]
        public bool InvokeOnLoggedOut { get; set; }

        /// <summary>
        /// Method that handles the redirect logic and execution.
        /// </summary>
        /// <param name="parameter">Not used, but is required by the base class.</param>
        protected override void Invoke(object parameter)
        {

            if (DesignTimeHelper.IsRuntime)
            {

                if (this.AlwaysRedirect
                    || this.AllowedRoles.Where(r => WebContextBase.Current.Authentication.User.IsInRole(r)).Count() == 0)
                {
                    //Uri navUri;

                    //if (Uri.TryCreate(this.NavigationUrl, UriKind.RelativeOrAbsolute, out navUri))
                    //    this.AssociatedObject.NavigationService.Navigate(navUri);

                    if (!String.IsNullOrEmpty(this.NavigationUrl))
                    {
                        Uri navUri;
                        if (Uri.TryCreate(this.NavigationUrl, UriKind.RelativeOrAbsolute, out navUri))
                            this.NavigationUri = navUri;
                    }

                    this.AssociatedObject.NavigationService.Navigate(this.NavigationUri);

                }

            }

        }

    }
}
